Skip to content

Conversation

girardof
Copy link
Contributor

@girardof girardof commented May 20, 2025

Proposed change

Add support for Schneider electric FLS/AIRLINK/4

Additional information

ZB Spec - Wireless Switch - 110422.pdf

This is my first time working with this library, and I have a few questions. If someone with more experience could help me, I would be very grateful:

  • I'm unsure how to test the changes. I have a Home Assistant instance running and one FLS/AIRLINK/4 switch, so I could in theory edit the code directly within my Home Assistant setup. But, if there’s a better approach, I’m open to suggestions.

  • The following cluster IDs aren't implemented:

    • 0x0003
    • 0x0004
    • 0x0005
    • 0x0006
    • 0x0008
    • 0x0019
    • 0x0102

Should they be implemented as well?

Checklist

  • The changes are tested and work correctly
  • pre-commit checks pass / the code has been formatted using Black
  • Tests have been added to verify that the new code works

Copy link

codecov bot commented May 20, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 91.23%. Comparing base (6b505b7) to head (8d1e2ae).
Report is 7 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #4081      +/-   ##
==========================================
+ Coverage   91.20%   91.23%   +0.03%     
==========================================
  Files         335      338       +3     
  Lines       10889    10907      +18     
==========================================
+ Hits         9931     9951      +20     
+ Misses        958      956       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@TheJulianJES
Copy link
Collaborator

I'm unsure how to test the changes. I have a Home Assistant instance running and one FLS/AIRLINK/4 switch, so I could in theory edit the code directly within my Home Assistant setup. But, if there’s a better approach, I’m open to suggestions.

Search "custom quirks zha". You can set up a folder and just drop this modified v2 quirk file in that. Those custom quirks will be preferred over the built-in ones.

The following cluster IDs aren't implemented: [...] Should they be implemented as well?

Those are all standard ZCL (Zigbee Cluster Library) clusters. They are already defined in zigpy and all entities should work as expected. Not quite sure what you mean with "implemented" here.
If there are custom attributes present on those clusters as well, you can create a class inheriting from both the original cluster (e.g. WindowCovering and CustomCluster), then use replaces as well.

SE seems to offer additional attributes on these default clusters, since other quirks also replace them. E.g. there are SEBasic and SEOnOff clusters here:

class SEBasic(CustomCluster, Basic):
"""Schneider Electric manufacturer specific Basic cluster."""
class AttributeDefs(Basic.AttributeDefs):
"""Attribute definitions."""
# The Application FW Version attribute specifies the firmware version of the application. The format of this
# attribute is XXX.YYY.ZZZ V.
# XXX = major version
# YYY = minor version
# ZZZ = patch version
# V = Build Type (One of the following: D = Development version, T0, T1 = Verification version, V = Validation
# version, R = Official Release version).
se_application_fw_version: Final = ZCLAttributeDef(
id=0xE001,
type=t.CharacterString,
is_manufacturer_specific=True,
)
# The Application HWVersion attribute specifies the hardware version of the application design in format
# AAA.BBB.CCC. Meaning:
# AAA - major version
# BBB - minor version
# CCC - patch version
# If version is 000.000.000, HW version is not available.
se_application_hw_version: Final = ZCLAttributeDef(
id=0xE002,
type=t.CharacterString,
is_manufacturer_specific=True,
)
# Device serial number. Hexadecimal string of 15 chars length.
se_device_serial_number: Final = ZCLAttributeDef(
id=0xE004,
type=t.CharacterString,
is_manufacturer_specific=True,
)
# The ProductIdentifier attribute specifies the unique internal numerical identifier of the product. See device
# description for this value.
se_product_identifier: Final = ZCLAttributeDef(
id=0xE007,
type=t.enum16,
is_manufacturer_specific=True,
)
# The ProductRange attribute specifies the name of the range to which the product belongs.
se_product_range: Final = ZCLAttributeDef(
id=0xE008,
type=t.CharacterString,
is_manufacturer_specific=True,
)
# The ProductModel attribute specifies the name of the product model. Same value as model identifier attribute
# 0x0005.
se_product_model: Final = ZCLAttributeDef(
id=0xE009,
type=t.CharacterString,
is_manufacturer_specific=True,
)
# The ProductFamily attribute specifies the name of the family to which the product belongs.
se_product_family: Final = ZCLAttributeDef(
id=0xE00A,
type=t.CharacterString,
is_manufacturer_specific=True,
)
# VendorURL, value: "http://www.schneider-electric.com"
se_vendor_url: Final = ZCLAttributeDef(
id=0xE00B,
type=t.CharacterString,
is_manufacturer_specific=True,
)
class SEOnTimeReloadOptions(t.bitmap8):
"""Valid values for the SE OnTimeReloadOptions attr."""
# OnTimeReload timer can be canceled by receiving OFF command -> light is going OFF immediately.
# If this bit is not set, the timer can not be canceled, it is always restarted.
OnTimeReloadCanceledByOffCommand = 0x1
# Impulse mode active. Whenever output should be switched ON, it will be switched ON only for 200msec.
# OnTimeReload attributes is ignored, also bit0 inside this attribute has no sense. If this bit is not set,
# impulse mode is disabled.
ImpulseMode = 0x2
class SEOnOff(CustomCluster, OnOff):
"""Schneider Electric manufacturer specific OnOff cluster."""
class AttributeDefs(OnOff.AttributeDefs):
"""Attribute definitions."""
# Has meaning only if attribute OnTimeReload is not 0. Defines number of seconds before the light is switched
# off automatically when the user is somehow inform the light will be switched off automatically. Value 0 or
# 0xFFFF disables pre-warning. For switch is just short switch OFF and ON, for dimmer device goes to 60
# percent and starts slowly dim down. During this time user can reload the time and postpone automatic switch
# off for time defined in OnTimeReload. If you enter value greater than 6553, after reboot you will read again
# value 6553. If you enter 0xFFFF, functionality will be disabled.
se_pre_warning_time: Final = ZCLAttributeDef(
id=0xE000,
type=t.uint16_t,
is_manufacturer_specific=True,
)
# Defines number of seconds before the light is switched off automatically. Time is in seconds.
# Value 0 disable the functionality. When brightness is changed, or ON command is received, timer is always
# restarted. Check OnTimeReloadOptions for possible impulse mode (if attribute is implemented).
se_on_time_reload: Final = ZCLAttributeDef(
id=0xE001,
type=t.uint32_t,
is_manufacturer_specific=True,
)
se_on_time_reload_options: Final = ZCLAttributeDef(
id=0xE002,
type=SEOnTimeReloadOptions,
is_manufacturer_specific=True,
)

You can also add the replaces for them to your (custom) quirk, then try the "Manage Zigbee device" menu to read the custom attributes and see if they're available for your device as well.

@girardof
Copy link
Contributor Author

Hi @TheJulianJES, thank you for taking the time to write your answer. I managed to use a custom quirks on my installation of HA. As you mentioned SEOnOff and SEBasic are needed for the quirk to work so I added them in a new commit.

After the changes implemented in the second commit the buttons are visible and using the physical switch toggle the controls in HA

Screenshot 2025-05-24 at 23 25 29

@TheJulianJES TheJulianJES added the needs review This PR should be reviewed soon, as it generally looks good. label May 25, 2025
@girardof
Copy link
Contributor Author

#4130 should be merged first, then SESpecific can be renamed into SESwitchConfiguration in the PR

@girardof
Copy link
Contributor Author

Unfortunately this PR is not ready to be merge, I can see device in home assistant and it's state (on/off). When pressing physically on the device the state in Home assistant change but when triggering the button from assistant I encounter the following issue:

Failed to perform the action switch/turn_on. Failed to turn on: <Status.UNSUPPORTED_CLUSTER: 195>

I'm still trying to find a solution; if anyone has any ideas about what might be causing the issue, I'm all ears.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs review This PR should be reviewed soon, as it generally looks good.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants